/*
 * Copyright 2020-2021 redragon.dongbin
 *
 * This file is part of redragon-erp/赤龙ERP.

 * redragon-erp/赤龙ERP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.

 * redragon-erp/赤龙ERP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with redragon-erp/赤龙ERP.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.erp.prod.mrp.service.spring;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.redragon.framework.hibernate.data.SnowFlake;
import org.redragon.framework.hibernate.model.Pages;
import org.redragon.framework.util.AutoBusinessCodeUtil;
import org.redragon.framework.util.ShiroUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.erp.hr.dao.model.HrStaffInfoRO;
import com.erp.hr.service.HrCommonService;
import com.erp.masterdata.common.service.MasterDataCommonService;
import com.erp.masterdata.material.dao.model.MdMaterial;
import com.erp.order.poa.dao.model.PoAgreementHead;
import com.erp.order.poa.dao.model.PoAgreementLine;
import com.erp.order.poa.service.PoAgreementHeadService;
import com.erp.order.poa.service.PoAgreementLineService;
import com.erp.prod.bom.dao.model.ProdBomHead;
import com.erp.prod.bom.service.ProdBomHeadService;
import com.erp.prod.craft.dao.model.ProdWorkCraft;
import com.erp.prod.craft.service.ProdWorkCraftService;
import com.erp.prod.mrp.dao.ProdMrpLineDao;
import com.erp.prod.mrp.dao.model.ProdMrpBillR;
import com.erp.prod.mrp.dao.model.ProdMrpLine;
import com.erp.prod.mrp.dao.model.ProdMrpLineCO;
import com.erp.prod.mrp.param.MrpParam;
import com.erp.prod.mrp.service.ProdMrpBillRService;
import com.erp.prod.mrp.service.ProdMrpLineService;
import com.erp.prod.wip.dao.model.ProdWipTask;
import com.erp.prod.wip.service.ProdWipTaskService;

@Service
@Transactional(rollbackFor=Exception.class)
public class ProdMrpLineServiceImpl implements ProdMrpLineService {

    //注入Dao
    @Autowired
    private ProdMrpLineDao prodMrpLineDao;
    @Autowired
    private HrCommonService hrCommonService;
    @Autowired
    private MasterDataCommonService masterDataCommonService;
    @Autowired
    private PoAgreementHeadService poAgreementHeadService;
    @Autowired
    private PoAgreementLineService poAgreementLineService;
    @Autowired
    private ProdMrpBillRService prodMrpPoaRService;
    @Autowired
    private ProdWipTaskService prodWipTaskService;
    @Autowired
    private ProdBomHeadService prodBomHeadService;
    @Autowired
    private ProdWorkCraftService prodWorkCraftService;
    
    @Override
    public void insertDataObject(ProdMrpLine obj) {
        this.prodMrpLineDao.insertDataObject(obj);
    }

    @Override
    public void updateDataObject(ProdMrpLine obj) {
        this.prodMrpLineDao.updateDataObject(obj);
    }
    
    @Override
    public void insertOrUpdateDataObject(ProdMrpLine obj) {
        this.prodMrpLineDao.insertOrUpdateDataObject(obj);
    }

    @Override
    public void deleteDataObject(ProdMrpLine obj) {
        this.prodMrpLineDao.deleteDataObject(obj);
    }

    @Override
    public List<ProdMrpLine> getDataObjects() {
        return this.prodMrpLineDao.getDataObjects();
    }

    @Override
    public ProdMrpLine getDataObject(int id) {
        return this.prodMrpLineDao.getDataObject(id);
    }

    @Override
    public ProdMrpLine getDataObject(String code) {
        return this.prodMrpLineDao.getDataObject(code);
    }

    @Override
    public List<ProdMrpLine> getDataObjects(ProdMrpLineCO paramObj) {
        return this.prodMrpLineDao.getDataObjects(paramObj);
    }

    @Override
    public List<ProdMrpLine> getDataObjects(Pages pages) {
        return this.prodMrpLineDao.getDataObjects(pages);
    }
    
    @Override
    public List<ProdMrpLine> getDataObjects(Pages pages, ProdMrpLineCO paramObj) {
        return this.prodMrpLineDao.getDataObjects(pages, paramObj);
    }
    
    @Override
    public List<Map<String, Object>> getDataObjectsArray(Pages pages, ProdMrpLineCO paramObj) {
        return this.prodMrpLineDao.getDataObjectsArray(pages, paramObj);
    }
    
    @Override
    public List<ProdMrpLine> getDataObjectsForDataAuth(String dataAuthSQL, Pages pages, ProdMrpLineCO paramObj) {
        return this.prodMrpLineDao.getDataObjectsForDataAuth(dataAuthSQL, pages, paramObj);
    }
    
    @Override
    public void deleteProdMrpLineByMrpHeadCode(String headCode) {
        this.prodMrpLineDao.deleteProdMrpLineByMrpHeadCode(headCode);
    }
    
    @Override
    public List<ProdMrpLine> getProdMrpLineListByMrpHeadCode(Pages pages, ProdMrpLineCO paramObj) {
        return this.prodMrpLineDao.getProdMrpLineListByMrpHeadCode(pages, paramObj);
    }
    
    @Override
    public List<ProdMrpLine> getProdMrpLineListByMrpHeadCode(String headCode) {
        return this.prodMrpLineDao.getProdMrpLineListByMrpHeadCode(headCode);
    }
    
    @Override
    public String autoCreatePoa(String mrpHeadCode, String mrpLineId) {
        //创建采购计划头
        PoAgreementHead poAgreementHead = new PoAgreementHead();
        //设置职员信息
        HrStaffInfoRO staffInfo = this.hrCommonService.getStaffInfo(ShiroUtil.getPrincipal());
        poAgreementHead.setStaffCode(staffInfo.getStaffCode());
        poAgreementHead.setDepartmentCode(staffInfo.getDepartmentCode());
        String sn = AutoBusinessCodeUtil.incrSerialNumberNumberCache(MrpParam.AUTO_POA_CODE_CACHE_KEY).toString();
        poAgreementHead.setPoHeadCode(AutoBusinessCodeUtil.getAutoBusinessCode("POA", mrpHeadCode, sn));
        poAgreementHead.setPoType("POATYPE03");
        poAgreementHead.setPoName(mrpHeadCode+"下达采购计划"+sn);
        poAgreementHead.setCurrencyCode("rmb");
        //插入采购计划协议头
        this.poAgreementHeadService.insertDataObject(poAgreementHead);
        
        Map<String, List<ProdMrpLine>> mrpLineMap = new HashMap<String, List<ProdMrpLine>>();
        
        //格式化计划行id
        String[] mrpLineIdArray = mrpLineId.split(":");
        //循环选择的计划行id
        for(String mrpLineIdTemp: mrpLineIdArray) {
            if(StringUtils.isNotBlank(mrpLineIdTemp)) {
                //获取计划行
                ProdMrpLine prodMrpLine = this.prodMrpLineDao.getDataObject(Integer.parseInt(mrpLineIdTemp));
                //判断当前计划行是否生成了采购计划,如果已经生成则跳过
                if(this.prodMrpPoaRService.isExistMrpLineRelateBill(prodMrpLine.getMrpHeadCode(), prodMrpLine.getMrpLineCode(), "POA")) {
                    continue;
                }
                //将相同物料的计划行合并
                if(mrpLineMap.containsKey(prodMrpLine.getMaterialCode())) {
                    mrpLineMap.get(prodMrpLine.getMaterialCode()).add(prodMrpLine);
                }else {
                    List<ProdMrpLine> temp = new ArrayList<ProdMrpLine>();
                    temp.add(prodMrpLine);
                    mrpLineMap.put(prodMrpLine.getMaterialCode(), temp);
                }
            }
        }
        
        //循环将相同物料行合并
        for(String materialCode: mrpLineMap.keySet()) {
            //获取相同物料的计划行
            List<ProdMrpLine> prodMrpLineTemp = mrpLineMap.get(materialCode);
            //计算合并后的计划数量
            BigDecimal quantity = new BigDecimal(0D);
            for(ProdMrpLine prodMrpLine: prodMrpLineTemp) {
                quantity = quantity.add(prodMrpLine.getPlanQuantity());
            }
            //创建采购计划行
            PoAgreementLine poAgreementLine = new PoAgreementLine();
//            poAgreementLine.setPoLineCode(SnowFlake.getConcurrentId().toString());
            poAgreementLine.setPoHeadCode(poAgreementHead.getPoHeadCode());
//            poAgreementLine.setMaterialCode(materialCode);
//            poAgreementLine.setQuantity(quantity);
            //获取物料数据
            MdMaterial mdMaterial = this.masterDataCommonService.getMdMaterialInfoCache(materialCode);
//            poAgreementLine.setUnit(mdMaterial.getMaterialUnit());
            //插入采购计划协议行
            this.poAgreementLineService.insertDataObject(poAgreementLine);
            
            //插入mrp与bill的关联表，由于根据物料合并但要记录合并前的关联关系
            for(ProdMrpLine prodMrpLine: prodMrpLineTemp) {
                ProdMrpBillR prodMrpPoaR = new ProdMrpBillR();
                prodMrpPoaR.setBillType("POA");
                prodMrpPoaR.setMrpHeadCode(prodMrpLine.getMrpHeadCode());
                prodMrpPoaR.setMrpLineCode(prodMrpLine.getMrpLineCode());
                prodMrpPoaR.setBillHeadCode(poAgreementLine.getPoHeadCode());
//                prodMrpPoaR.setBillLineCode(poAgreementLine.getPoLineCode());
                this.prodMrpPoaRService.insertDataObject(prodMrpPoaR);
            }
            
        }
        
        //返回json数据
        return "{\"errCode\":0, \"errMsg\": \"\", \"poHeadId\": "+poAgreementHead.getPoHeadId()+", \"poHeadCode\": \""+poAgreementHead.getPoHeadCode()+"\"}";
    }
    
    @Override
    public String autoCreateWipTask(String mrpHeadCode, String mrpLineId) {
        //判断单个mrp行
        if(!mrpLineId.contains(":")) {
            //获取mrp行
            ProdMrpLine prodMrpLine = this.prodMrpLineDao.getDataObject(Integer.parseInt(mrpLineId));
            
            if(prodMrpLine!=null) {
                //判断当前计划行是否生成了生产任务,如果已经生成则跳过
                if(this.prodMrpPoaRService.isExistMrpLineRelateBill(prodMrpLine.getMrpHeadCode(), prodMrpLine.getMrpLineCode(), "WIP")) {
                    //返回json数据
                    return "{\"errCode\":-1, \"errMsg\": \"当前计划行已生成生产任务\"}";
                }
                
                //创建生产任务头
                ProdWipTask prodWipTask = new ProdWipTask();
                String sn = AutoBusinessCodeUtil.incrSerialNumberNumberCache(MrpParam.AUTO_WIP_TASK_CODE_CACHE_KEY).toString();
                prodWipTask.setTaskCode(AutoBusinessCodeUtil.getAutoBusinessCode("WIP-TASK", prodMrpLine.getMrpHeadCode(), sn));
                prodWipTask.setTaskName(prodMrpLine.getMrpHeadCode()+"下达生产任务"+sn);
                //设置职员信息
                HrStaffInfoRO staffInfo = this.hrCommonService.getStaffInfo(ShiroUtil.getPrincipal());
                prodWipTask.setStaffCode(staffInfo.getStaffCode());
                prodWipTask.setDepartmentCode(staffInfo.getDepartmentCode());
                prodWipTask.setTaskType("STANDARD");
                prodWipTask.setMaterialCode(prodMrpLine.getMaterialCode());
                prodWipTask.setMaterialUnit(this.masterDataCommonService.getMdMaterialInfoCache(prodMrpLine.getMaterialCode()).getMaterialUnit());
                prodWipTask.setQuantity(prodMrpLine.getPlanQuantity());
                prodWipTask.setStartDate(prodMrpLine.getPlanStartDate());
                prodWipTask.setEndDate(prodMrpLine.getPlanEndDate());
                prodWipTask.setTaskStatus("NOASSIGN");
                //获取bom信息
                ProdBomHead prodBomHead = this.prodBomHeadService.getProdBomHeadByMaterialCode(prodMrpLine.getMaterialCode());
                if(prodBomHead!=null) {
                    prodWipTask.setBomHeadCode(prodBomHead.getBomHeadCode());
                }
                //获取工艺路线信息
                ProdWorkCraft prodWorkCraft = this.prodWorkCraftService.getProdWorkCraftByMaterialCode(prodMrpLine.getMaterialCode());
                if(prodWorkCraft!=null) {
                    prodWipTask.setCraftCode(prodWorkCraft.getCraftCode());
                }
                
                //插入生产任务头
                this.prodWipTaskService.insertDataObject(prodWipTask);
                
                //插入mrp与bill的关联表
                ProdMrpBillR prodMrpPoaR = new ProdMrpBillR();
                prodMrpPoaR.setBillType("WIP");
                prodMrpPoaR.setMrpHeadCode(prodMrpLine.getMrpHeadCode());
                prodMrpPoaR.setMrpLineCode(prodMrpLine.getMrpLineCode());
                prodMrpPoaR.setBillHeadCode(prodWipTask.getTaskCode());
                this.prodMrpPoaRService.insertDataObject(prodMrpPoaR);
                
                //返回json数据
                return "{\"errCode\":0, \"errMsg\": \"\", \"taskId\": "+prodWipTask.getTaskId()+", \"taskCode\": \""+prodWipTask.getTaskCode()+"\"}";
            
            }
        }else {
            //返回json数据
            return "{\"errCode\":-1, \"errMsg\": \"只能选择一个计划行\"}";
        }
        
        //返回json数据
        return "{\"errCode\":-1, \"errMsg\": \"生成生产任务失败\"}";
    }
    
}